package com.atguigu.srb.core.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.common.exception.Assert;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.srb.core.enums.LendStatusEnum;
import com.atguigu.srb.core.enums.TransTypeEnum;
import com.atguigu.srb.core.hfb.FormHelper;
import com.atguigu.srb.core.hfb.HfbConst;
import com.atguigu.srb.core.hfb.RequestHelper;
import com.atguigu.srb.core.mapper.*;
import com.atguigu.srb.core.pojo.bo.TransFlowBO;
import com.atguigu.srb.core.pojo.entity.*;
import com.atguigu.srb.core.service.*;
import com.atguigu.srb.core.utils.LendNoUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 还款记录表 服务实现类
 * </p>
 *
 * @author tjf
 * @since 2022-01-03
 */
@Service
public class LendReturnServiceImpl extends ServiceImpl<LendReturnMapper, LendReturn> implements LendReturnService {
    @Resource
    private LendMapper lendMapper;

    @Resource
    private TransFlowMapper transFlowMapper;

    @Resource
    private UserAccountMapper userAccountMapper;

    @Resource
    private LendItemMapper lendItemMapper;

    private final UserBindService userBindService;

    private final LendItemReturnService lendItemReturnService;

    private final UserAccountService userAccountService;

    private final TransFlowService transFlowService;

    public LendReturnServiceImpl(UserBindService userBindService, LendItemReturnService lendItemReturnService, UserAccountService userAccountService, TransFlowService transFlowService) {
        this.userBindService = userBindService;
        this.lendItemReturnService = lendItemReturnService;
        this.userAccountService = userAccountService;
        this.transFlowService = transFlowService;
    }

    @Override
    public List<LendReturn> selectByLendId(Long lendId) {
        LambdaQueryWrapper<LendReturn> lendReturnLambdaQueryWrapper = new LambdaQueryWrapper<>();
        lendReturnLambdaQueryWrapper.eq(LendReturn::getLendId, lendId);
        return baseMapper.selectList(lendReturnLambdaQueryWrapper);
    }

    @Override
    public String commitReturn(Long lendReturnId, Long userId) {
        // 校验用户余额充足
        BigDecimal account = userAccountService.getAccount(userId);
        LendReturn lendReturn = baseMapper.selectById(lendReturnId);
        Assert.isTrue(account.doubleValue() >= lendReturn.getTotal().doubleValue(), ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);

        Lend lend = lendMapper.selectById(lendReturn.getLendId());
        String bindCode = userBindService.getBindCodeByUserId(userId);

        // 组装参数
        HashMap<String, Object> map = new HashMap<>();
        map.put("agentId", HfbConst.AGENT_ID);
        // 商户商品名称
        map.put("agentGoodsName", lend.getTitle());
        // 批次号
        map.put("agentBatchNo", lendReturn.getReturnNo());
        // 还款人绑定协议号
        map.put("fromBindCode", bindCode);
        // 还款总额
        map.put("totalAmt", lendReturn.getTotal());
        map.put("note", "");

        // 还款明细
        List<Map<String, Object>> lendItemReturnDetailList = lendItemReturnService.addReturnDetail(lendReturnId);
        map.put("data", JSONObject.toJSONString(lendItemReturnDetailList));

        map.put("voteFeeAmt", new BigDecimal("0"));
        map.put("notifyUrl", HfbConst.BORROW_RETURN_NOTIFY_URL);
        map.put("returnUrl", HfbConst.BORROW_RETURN_RETURN_URL);
        map.put("timestamp", RequestHelper.getTimestamp());
        map.put("sign", RequestHelper.getSign(map));

        return FormHelper.buildForm(HfbConst.BORROW_RETURN_URL, map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String notify(Map<String, Object> map) {
        // 幂等性判断，判断流水表中是否有记录
        String agentBatchNo = (String) map.get("agentBatchNo");
        LambdaQueryWrapper<TransFlow> transFlowLambdaQueryWrapper = new LambdaQueryWrapper<>();
        transFlowLambdaQueryWrapper.eq(TransFlow::getTransNo, agentBatchNo);
        boolean exists = transFlowMapper.exists(transFlowLambdaQueryWrapper);
        if (exists) {
            log.warn("幂等性返回");
            return "success";
        }

        // 获取还款数据
        LambdaQueryWrapper<LendReturn> lendReturnLambdaQueryWrapper = new LambdaQueryWrapper<>();
        lendReturnLambdaQueryWrapper.eq(LendReturn::getReturnNo, agentBatchNo);
        LendReturn lendReturn = baseMapper.selectOne(lendReturnLambdaQueryWrapper);

        // 更新还款状态
        String voteFeeAmt = (String) map.get("voteFeeAmt");
        lendReturn.setStatus(1);
        lendReturn.setFee(new BigDecimal(voteFeeAmt));
        lendReturn.setRealReturnTime(LocalDateTime.now());
        baseMapper.updateById(lendReturn);

        // 更新标的信息
        // 最后一次还款更新标的状态
        Lend lend = lendMapper.selectById(lendReturn.getLendId());
        if (lendReturn.getLast()) {
            lend.setStatus(LendStatusEnum.PAY_OK.getStatus());
            lendMapper.updateById(lend);
        }

        // 借款账号转出金额
        String totalAmt = (String) map.get("totalAmt");
        String bindCode = userBindService.getBindCodeByUserId(lendReturn.getUserId());
        userAccountMapper.updateAccount(bindCode,  new BigDecimal(totalAmt).negate(), null);

        // 借款人交易流水
        TransFlowBO transFlowBO = new TransFlowBO(
                agentBatchNo,
                bindCode,
                new BigDecimal(totalAmt),
                TransTypeEnum.RETURN_DOWN,
                "借款人还款扣减，项目编号：" + lend.getLendNo() + ", 项目名称：" + lend.getTitle()
        );
        transFlowService.saveTransFlow(transFlowBO);

        // 获取回款明细
        List<LendItemReturn> lendItemReturnList = lendItemReturnService.selectLendItemReturnList(lendReturn.getId());
        lendItemReturnList.forEach(lendItemReturn -> {
            // 更新回款状态
            lendItemReturn.setStatus(1);
            lendItemReturn.setRealReturnTime(LocalDateTime.now());

            // 更新出借信息
            LendItem lendItem = lendItemMapper.selectById(lendItemReturn.getLendItemId());
            lendItem.setRealAmount(lendItem.getRealAmount().add(lendItemReturn.getInterest()));
            lendItemMapper.updateById(lendItem);

            // 投资账号转入金额
            String investBindCode = userBindService.getBindCodeByUserId(lendItemReturn.getInvestUserId());
            userAccountMapper.updateAccount(investBindCode, lendItemReturn.getTotal(), null);

            // 投资账号交易流水
            TransFlowBO investTransFlowBO = new TransFlowBO(
                    LendNoUtils.getReturnItemNo(),
                    investBindCode,
                    lendItemReturn.getTotal(),
                    TransTypeEnum.INVEST_BACK,
                    "还款到账，项目编号：" + lend.getLendNo() + ", 项目名称：" + lend.getTitle()
            );
            transFlowService.saveTransFlow(investTransFlowBO);
        });
        lendItemReturnService.saveOrUpdateBatch(lendItemReturnList);

        return "success";
    }
}
